package pers.dawnyang.modular.system.service.impl;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import pers.dawnyang.common.annotation.SP;
import pers.dawnyang.common.constant.Const;
import pers.dawnyang.common.domain.entity.SysDept;
import pers.dawnyang.common.domain.entity.SysUser;
import pers.dawnyang.common.domain.entity.SysUserDept;
import pers.dawnyang.common.domain.entity.SysUserRole;
import pers.dawnyang.common.enums.ConfigEnum;
import pers.dawnyang.common.util.MyTools;
import pers.dawnyang.common.util.math.RandomUtil;
import pers.dawnyang.config.cache.ConfigUtils;
import pers.dawnyang.config.shiro.ShiroUtil;
import pers.dawnyang.modular.system.domain.request.user.UserDeptReqU;
import pers.dawnyang.modular.system.domain.request.user.UserExcelReq;
import pers.dawnyang.modular.system.domain.request.user.UserReqR;
import pers.dawnyang.modular.system.domain.request.user.UserRoleReqU;
import pers.dawnyang.modular.system.domain.response.user.UserDeptRes;
import pers.dawnyang.modular.system.domain.response.user.UserExcelRes;
import pers.dawnyang.modular.system.domain.response.user.UserRes;
import pers.dawnyang.modular.system.domain.response.user.UserRoleRes;
import pers.dawnyang.modular.system.excelListener.UserExcelResListener;
import pers.dawnyang.modular.system.mapper.SysDeptMapper;
import pers.dawnyang.modular.system.mapper.SysUserDeptMapper;
import pers.dawnyang.modular.system.mapper.SysUserMapper;
import pers.dawnyang.modular.system.mapper.SysUserRoleMapper;
import pers.dawnyang.modular.system.service.UserService;


/**
 * @author dawn
 * @date 2021/02/08
 */
@Service
public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements UserService {

  @Autowired
  private SysUserMapper sysUserMapper;

  @Autowired
  private SysDeptMapper sysDeptMapper;

  @Autowired
  private SysUserRoleMapper sysUserRoleMapper;

  @Autowired
  private SysUserDeptMapper sysUserDeptMapper;

  @SP
  @Override
  public Page<UserRes> getPage(Page<UserRes> page, UserReqR req) {
    // SqlTools.montageSql(req);
    Page<UserRes> resPage = sysUserMapper.getPage(page, req);
    return resPage;
  }

  @Override
  public List<SysUserDept> getUserDeptList(Long userId) {
    LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
    lqw.eq(SysUserDept::getUserId, userId);
    return sysUserDeptMapper.selectList(lqw);
  }

  @Override
  public void saveUserRole(UserRoleReqU req) {
    Long userId = req.getUserId();
    String lastRoleIds = req.getLastRoleIds();
    String roleIds = req.getRoleIds();
    List<String> add = MyTools.getDiff(lastRoleIds, roleIds);
    if (add != null && add.size() > 0) {
      for (String str : add) {
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(userId);
        sysUserRole.setRoleId(Long.valueOf(str));
        sysUserRoleMapper.insert(sysUserRole);
      }
    }
    List<String> delete = MyTools.getDiff(roleIds, lastRoleIds);
    if (delete != null && delete.size() > 0) {
      for (String str : delete) {
        LambdaQueryWrapper<SysUserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUserRole::getRoleId, Long.valueOf(str));
        lqw.eq(SysUserRole::getUserId, userId);
        sysUserRoleMapper.delete(lqw);
      }
    }

  }

  @Override
  public List<UserDeptRes> getUserDept(Long userId) {
    List<UserDeptRes> allDept = sysUserMapper.getAllDept();
    List<UserDeptRes> userDept = sysUserMapper.getUserDept(userId);
    allDept.forEach(res -> {
      if (userDept.contains(res)) {
        res.setCheckArr("1");
      } else {
        res.setCheckArr("0");
      }
    });
    return allDept;
  }

  @Override
  public List<UserRoleRes> getUserRole(Long userId) {
    List<UserRoleRes> allRole = sysUserMapper.getAllRole();
    List<UserRoleRes> userRole = sysUserMapper.getUserRole(userId);

    allRole.forEach(res -> {
      if (userRole.contains(res)) {
        res.setLAY_CHECKED(true);
      } else {
        res.setLAY_CHECKED(false);
      }
    });

    return allRole;
  }

  @Override
  public void saveUserDept(UserDeptReqU req) {
    Long userId = req.getUserId();
    String lastDeptIds = req.getLastDeptIds();
    String deptIds = req.getDeptIds();
    List<String> add = MyTools.getDiff(lastDeptIds, deptIds);
    if (add != null && add.size() > 0) {
      for (String str : add) {
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(userId);
        sysUserDept.setDeptId(Long.valueOf(str));
        sysUserDeptMapper.insert(sysUserDept);
      }
    }
    List<String> delete = MyTools.getDiff(deptIds, lastDeptIds);
    if (delete != null && delete.size() > 0) {
      for (String str : delete) {
        LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUserDept::getDeptId, Long.valueOf(str));
        lqw.eq(SysUserDept::getUserId, userId);
        sysUserDeptMapper.delete(lqw);
      }
    }
  }

  @Override
  public UserRes getUserDetail(Long userId) {
    SysUser sysUser = sysUserMapper.selectById(userId);
    UserRes userRes = new UserRes();
    BeanUtils.copyProperties(sysUser, userRes);
    List<UserRoleRes> userRole = sysUserMapper.getUserRole(userId);
    // List<UserDeptRes> userDept =
    // sysUserMapper.getUserDept(userId);

    List<UserDeptRes> userDept = new ArrayList<>();
    LambdaQueryWrapper<SysUserDept> lqw = new LambdaQueryWrapper<>();
    lqw.eq(SysUserDept::getUserId, userId);
    List<SysUserDept> resList = sysUserDeptMapper.selectList(lqw);
    if (null != resList && resList.size() > 0) {
      for (SysUserDept sysUserDept : resList) {
        UserDeptRes userDeptRes = new UserDeptRes();
        Long deptId = sysUserDept.getDeptId();
        SysDept sysDept = sysDeptMapper.selectById(deptId);
        String deptName = sysDept.getDeptName();
        String pids = sysDept.getPids();
        String[] pidArr = pids.split(",");
        String pDeptName = "";
        for (String pid : pidArr) {
          if (!"0".equals(pid)) {
            SysDept sysDeptP = sysDeptMapper.selectById(pid);
            if (null != sysDeptP) {
              pDeptName += sysDeptP.getDeptName() + "/";
            }
          }
        }
        pDeptName += deptName;
        userDeptRes.setDeptId(deptId);
        userDeptRes.setDeptName(pDeptName);
        userDept.add(userDeptRes);
      }

    }

    userRes.setRoleList(userRole);
    userRes.setDeptList(userDept);
    return userRes;
  }

  @Override
  public void resetPwd(Long userId) {
    String salt = RandomUtil.getRandomString(Const.SALT_FIGURE);
    String defaultPwd = ConfigUtils.getValue(ConfigEnum.DEFAULT_PWD.getConfigCode());
    String newPwdMd5Hash = new Md5Hash(defaultPwd, salt, Const.MD5_NUM).toString();
    SysUser user = new SysUser();
    user.setPassword(newPwdMd5Hash);
    user.setSalt(salt);
    LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
    lqw.eq(SysUser::getUserId, userId);
    sysUserMapper.update(user, lqw);
  }

  @SP
  @Override
  public List<UserExcelRes> export(UserReqR req) {
    List<UserExcelRes> records = sysUserMapper.getUserExcel(req);
    return records;
  }

  @Override
  public Long getUserMinRoleLevel(Long userId) {
    return sysUserMapper.getUserMinRoleLevel(userId);
  }

  @Override
  public boolean checkRoleLevel(Long userId) {
    if (userId != ShiroUtil.getUserId()) {
      Long minRoleLevel = ShiroUtil.getUserMinRoleLevel();
      Long roleLevel = sysUserMapper.getUserMinRoleLevel(userId);
      if (null != roleLevel) {
        if (roleLevel <= minRoleLevel) {
          return false;
        }
      }
    }
    return true;
  }

  @Override
  public Long getMinRoleLevelByRoleIds(String roleIds) {
    String[] roleIdsArr = roleIds.split(",");
    return sysUserMapper.getMinRoleLevelByRoleIds(roleIdsArr);
  }

  @Override
  public String uploadExcel(MultipartFile file) throws IOException {
    UserExcelResListener userExcelResListener = new UserExcelResListener(new UserServiceImpl());
    EasyExcel.read(file.getInputStream(), UserExcelReq.class, userExcelResListener).sheet()
        .doRead();
    return userExcelResListener.getExcelMsg().toString();
  }


}
